home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS04.ADF
/
text
/
consoleIO.txt
< prev
next >
Wrap
Text File
|
1985-12-04
|
57KB
|
1,979 lines
Chapter 1
Console Device
This chapter describes how you do console (keyboard and screen)
input and output on the Amiga. The console device acts like an
enhanced ASCII terminal. It obeys many of the standard ANSI
sequences as well as additional special sequences unique to the
Amiga.
1.1. INTRODUCTION
Console I/O is tied closely to the Amiga Intuition interface; a
console must be tied to a window that is already opened. From
the Window data structure, the console device determines how many
characters it can display on a line and how many lines of text it
can display in a window without clipping at any edge.
You can open the console device many times, if you wish. The
result of each open call is a new console unit. AmigaDOS and
Intuition see to it that only one window is the currently active
one, and its console, if any, is the only one (with a few excep-
tions) that receives notification of input events, such as keys-
trokes. Later in this chapter you'll see that other Intuition
events can be sensed by the console device as well.
NOTE: For this entire chapter the characters "<CSI>" represent
the Control Sequence Introducer. For output you may either use
the two-character sequence "<Esc>[" or the one-byte value $9B
(hex). For input you will receive $9B's.
1.2. SYSTEM FUNCTIONS
The various system functions, such as DoIO(), SendIO(), Abor-
tIO(), CheckIO() and so on operate normally. The only caveats
are that the CMD_WRITE may cause the caller to wait internally,
even with SendIO(), and a task waiting on response from a console
is at the user's whim. If a user never reselects that window,
and the console response provides the only wakeup-call, that task
may well sleep indefinitely.
November 17, 1985
- 2 -
1.3. CONSOLE I/O
The console device may be thought of as a kind of a terminal.
You send a character stream to the console device. You also
receive a character stream from the console device. These
streams may be characters or special sequences.
Console character screen output (as compared to console command
sequence transmission) outputs all standard printable characters
(character values hex 20 thru 7E and A0 thru FF) normally. Many
control characters such as BACKSPACE and RETURN are translated
into their exact ANSI equivalent actions. The line-feed charac-
ter is a bit different, in that it can be translated into a new-
line character. The net effect is that the cursor moves to the
first column of the next line whenever a <LF> is displayed. This
is set via the mode control sequences discussed under "Control
Sequences for Screen Output".
If you read from the console device, the keyboard inputs are
preprocessed for you. You will get the ASCII characters such as
"B". Most normal text gathering programs will read from the con-
sole device in this manner. Special programs like word proces-
sors and music keyboard programs will use raw input. Keys are
converted via the keymap associated with the unit.
The sections below deal with the following topics:
o Setting up for console I/O (creating an I/O request
structure)
o Writing to the console to control its behavior
o Reading from the console
o Closing down a console device
This section shows you how to set up for console I/O.
1.4. CREATING AN I/O REQUEST
Console I/O, like other devices, requires that you create an I/O
request message that you pass to the console device for process-
ing. The message contains the command, as well as a data area.
In the data area, for a write, there will be a pointer to the
stream of information you wish to write to the console. For a
read, this data pointer shows where the console is to copy the
data it has for you. There is also a length field that says how
many characters (maximum) are to be copied either from or to the
console device.
November 17, 1985
- 3 -
Here is a program fragment that can be used to create the message
block that you use for console communications.
For writing to the console:
struct IOStdReq *consoleWriteMsg; /* I/O request block pointer */
struct Port *consoleWritePort; /* a port at which to receive replies*/
consoleWritePort = CreatePort("mycon.write",0);
if(consoleWritePort == 0) exit(100); /* error in createport */
consoleWriteMsg = CreateStdIO(consoleWritePort);
if(consoleWriteMsg == 0) exit(200); /* error in createstdio */
For reading from the console:
struct IOStdReq *consoleReadMsg;
/* I/O request block pointer */
struct Port *consoleReadPort;
/* a port at which to receive replies */
consoleReadPort = CreatePort("mycon.read",0);
if(consoleReadPort == 0) exit(300); /* error in createport */
consoleReadMsg = CreateStdIO(consoleReadPort);
if(consoleReadMsg == 0) exit(400); /* error in createstdio */
These fragments show two messages and ports being set up. You
would use this if you want to have a read command continuously
queued up while using a separate message with its associated port
to send control command sequences to the console.
In addition, if you want to queue up multiple commands to the
console, you may wish to create multiple messages (but probably
just one port for receiving replied messages from the device).
1.5. OPENING A CONSOLE DEVICE
For other devices, you normally use OpenDevice() to pass an unin-
itialized IORequest block to the device. For a console device,
this is slightly different. You must have initialized two fields
in the request block; namely, the data pointer and the length
field. Here is a subroutine that can be used to open a console
device (attach it to an existing window). It assumes that
intuition.library is already open, a window has also been opened,
and this new console is to be attached to the open window.
November 17, 1985
- 4 -
/* this function returns a value of 0 if the console
* device opened correctly and a nonzero value (the error
* returned from OpenDevice) if there was an error.
*/
OpenConsole(request,window)
struct IOStdReq *request;
struct Window *window;
{
/* Open a console device */
request->io_Data = (char *) window;
request->io_Length = sizeof(*window);
return(OpenDevice("console.device", 0, request, 0));
}
To perform console I/O, you fill in fields of the console I/O
standard request, and pass this block to the console device using
one of the normal I/O functions. When the console device has
completed the action, the device returns the message block to the
port you have designated within the message itself. The function
CreateStdIO() initializes the message to contain the address of
the ReplyPort.
Here are subroutines that uses the IOStdReq created above. Note
that the IOStdReq itself contains a pointer to the device with
which it is communicating so a single function can be used to
communicate with multiple consoles.
November 17, 1985
- 5 -
/* output a single character to a specified console */
ConPutChar(request,character)
struct IOStdReq *request;
char character;
{
request->io_Command = CMD_WRITE;
request->io_Data = &character;
request->io_Length = 1;
DoIO(request);
return;
}
/* output a stream of known length to a console */
ConWrite(request,string,length)
struct IOStdReq *request;
char *string;
int length;
{
request->io_Command = CMD_WRITE;
request->io_Data = string;
request->io_Length = length;
DoIO(request);
return;
}
/* output a NULL-terminated string of characters to a console */
ConPutStr(request,string)
struct IOStdReq *request;
char *string;
{
request->io_Command = CMD_WRITE;
request->io_Data = string;
request->io_Length = -1; /* tells console to end when it
* sees a terminating zero on
* the string. */
DoIO(request);
return;
}
1.6. CONTROL SEQUENCES FOR SCREEN OUTPUT
Here is a list of the functions that the console device supports,
along with the character stream that you must send to the console
to produce the effect. Where the function table indicates multi-
ple characters, it is more efficient to use the ConWrite() func-
tion rather than ConPutChar() since it avoids the overhead of
transfering the message block multiple times. The table below
uses the second form of <CSI>, that is, the hex value 9B, to
November 17, 1985
- 6 -
minimize the number of characters to be transmitted to produce a
function.
In the table below, if an item is enclosed in square brackets, it
is an optional item and may be omitted. For example, for INSERT
[N] CHARACTERS, the value for N or M is shown as optional. The
console device responds to such optional items by treating the
value of N as if it is not specified.
The value of N or M is always a decimal number, having one or
more ASCII digits to express its value.
Table 1-1: Console Control Sequences
COMMAND SEQUENCE OF CHARACTERS (in hexadecimal)
BACKSPACE (move left one column) 08
LINE FEED (move down one text line 0A
as specified by the mode
function below)
VERTICAL TAB (move up one text line) 0B
FORM FEED (clear the console's screen) 0C
CARRIAGE RETURN (move to first column) 0D
SHIFT IN (undo SHIFT OUT) OE
SHIFT OUT (set MSB of each character 0F
before displaying)
ESC (escape; can be part of the control 1B
sequence introducer)
CSI (control sequence introducer) ESC [
RESET TO INITIAL STATE 9B 63
INSERT [N] CHARACTERS 9B [N] 40
(Inserts one or more spaces, shifting the
remainder of the line to the right.)
CURSOR UP [N] CHARACTER POSITIONS 9B [N] 41
(default = 1)
CURSOR DOWN [N] CHARACTER POSITIONS 9B [N] 42
(default = 1)
CURSOR FORWARD [N] CHARACTER POSITIONS 9B [N] 43
(default = 1)
CURSOR BACKWARD [N] CHARACTER 9B [N] 44
POSITIONS (default = 1)
CURSOR NEXT LINE [N] (to column 1) 9B [N] 45
CURSOR PRECEDING LINE [N] 9B [N] 46
(to column 1)
MOVE CURSOR TO ROW; COLUMN 9B [N] [3B N] 48
where N is row, M is column, and
semicolon (hex 3B) must be present
as a separator, or if row is left
out, so the console device can tell
that the number after the semicolon
actually represents the column number.
ERASE TO END OF DISPLAY 9B 4A
ERASE TO END OF LINE 9B 4B
November 17, 1985
- 7 -
INSERT LINE (above the line containing 9B 4C
the cursor)
DELETE LINE (remove current line, move 9B 4D
all lines up one position to fill
gap, blank bottom line)
DELETE CHARACTER [N] (that cursor is 9B [N] 50
sitting on and to the right if
[N] is specified)
SCROLL UP [N] LINES (Remove line(s) from 9B [N] 53
top of screen, move all other lines
down, blanks [N] bottom lines).
SCROLL DOWN [N] LINES (Remove line(s) 9B [N] 54
from bottom of screen, move all
other lines up, blanks [N] top lines).
SET MODE (cause LINEFEED to respond as 9B 32 30 68
RETURN-LINEFEED)
RESET MODE (cause LINEFEED to respond 9B 32 30 6C
only as LINEFEED)
DEVICE STATUS REPORT (cause console to 9B 6E
insert into your read-stream a CURSOR
POSITION REPORT; see "Reading from
the Console" for more info).
SELECT GRAPHIC RENDITION See note below. [S];[F];[B]
(select text style, foreground color,
background color)
NOTE: For SELECT GRAPHIC RENDITION, any number of
parameters, in any order, are valid. They are
separated by semicolons.
<style> =
0 plain text
1 bold-face
3 italic
4 underscore
7 inverse-video
<fg> =
30 - 37 selecting system colors 0-7 for foreground
transmitted as two ASCII characters
<bg> =
40 - 47 selecting system colors 0-7 for background
transmitted as two ASCII characters
For example, to select bold-face, with color 3 as
foreground and color 0 as background, send the
sequence:
9B 31 3B 33 33 3B 34 30 6D
November 17, 1985
- 8 -
representing the ASCII sequence:
"<CSI>1;33;40m"
where <CSI> is the control sequence introducer, here
used as the single-character value 9B hex.
The following are not ANSI standard sequences; they are
private Amiga sequences.
In the four command descriptions that follow, length,
width, and offset are comprised of one or more ASCII
digits, defining a decimal value.
COMMAND SEQUENCE OF CHARACTERS (in hexadecimal)
SET PAGE LENGTH (in character raster lines,
causes console to recalculate,
using current font, how many text 9B <length> 74
lines will fit on the page.
SET LINE LENGTH (in character positions,
using current font, how many characters
should be placed on each line). 9B <width> 75
SET LEFT OFFSET (in raster columns, how far
from the left of the window
should the text begin). 9B <offset> 78
SET TOP OFFSET (in raster lines, how far
from the top of the window's
RastPort should the topmost
line of the character begin). 9B <offset> 79
NOTE: The console normally handles the above four
functions automatically. To allow it to do so again
after setting your own values, you can send the func-
tion without a parameter.
COMMAND SEQUENCE OF CHARACTERS (in hexadecimal)
SET RAW EVENTS-see the separate topic
"Selecting Raw Input Events"
below for more details.
RESET RAW EVENTS-see "Selecting Raw Input Events" below.
November 17, 1985
- 9 -
SET CURSOR RENDITION - make the cursor
visible or invisible:
invisible: 9B 30 70
visible: 9B 70
WINDOW STATUS REQUEST - ask the console
device to tell you the current
bounds of the window, in
upper and lower row and column
character positions.
(User may have resized or repositioned
it). See "Window Bounds Report" below. 9B 71
Examples
Move cursor right by 1:
Character string equivalents: <CSI>C or <CSI>1C
Numeric (hex) equivalents: 9B 43 9B 31 43
Move cursor right by 20:
Character string equivalent: <CSI>20C
Numeric (hex) equivalent: 9B 32 30 43
Move cursor to upper left corner (home):
Character string equivalents:
<CSI>H or
<CSI>1;1H or
<CSI>;1H or
<CSI>1;H
Numeric (hex) equivalents:
9B 48
9B 31 3B 31 48
9B 3B 31 48
9B 31 3B 48
Move cursor to the forth column of the first line of the window:
November 17, 1985
- 10 -
Character string equivalents:
<CSI>1;4H or
<CSI>;4H
Numeric (hex) equivalents:
9B 31 3B 34 48
9B 3B 34 48
Clear the screen:
Character string equivalents:
<FF> or CTRL-L {clear screen character} or
<CSI>H<CSI>J {home and clear to end of screen} or
Numeric (hex) equivalents:
0C
9B 48 9B 4A
Reading input from the console device returns an ANSI 3.64 stan-
dard byte stream. This stream may contain normal characters
and/or RAW input event information. You may also request other
RAW input events using the SET RAW EVENTS and RESET RAW EVENTS
control sequences discussed below. See "Selection of Raw Input
Events".
The following subroutines are useful for setting up for console
reads. Only a single-character-at-a-time version is shown here.
NOTE: This example does not illustrate the fact that a request
for more than one character can be satisfied by only one, thus
requiring you to look at io_actual.
/* queue up a read request to a console, show where to
* put the character when ready to be returned. Most
* efficient if this is called right after console is
* opened */
QueueRead(request,whereto)
struct IOStdReq *request;
char *whereto;
{
request->io_Command = CMD_READ;
request->io_Data = whereto;
request->io_Length = 1;
SendIO(request);
return;
}
November 17, 1985
- 11 -
/* see if there is a character to read. If none, don't wait,
* come back with a value of -1 */
int
ConMayGetChar(consolePort,request,whereto)
struct Port *consolePort
struct IOStdReq *request;
char *whereto;
{
register temp;
if ( GetMsg(consolePort) == NULL ) return(-1);
temp = *whereto;
QueueRead(request,whereto);
return(temp);
}
/* go and get a character; put the task to sleep if
* there isn't one present */
UBYTE
ConGetChar(consolePort,request,whereto)
struct IOStdReq *request;
struct Port *consolePort;
char *whereto;
{
register temp;
while((GetMsg(consolePort) == NULL)) WaitPort(consolePort);
temp = *whereto; /* get the character */
QueueRead(request,whereto);
return(temp);
}
For the most part, keys whose keycaps are labeled with ANSI stan-
dard characters will ordinarily be translated into their ASCII
equivalent character by the console device through the use of its
keymap. A separate section in this chapter has been dedicated to
the method used to establish a keymap and the internal organiza-
tion of the keymap.
For keys other than those with normal ASCII equivalents, an
escape sequence is generated and inserted into your input stream.
For example, in the default state (no raw input events selected)
the function and arrow keys will cause the following sequences to
be inserted in the input stream:
November 17, 1985
- 12 -
Table 1-2: Special Key Report Sequences
center box; c c l.
KEY UNSHIFTED SENDS SHIFTED SENDS
F1 <CSI>0~ <CSI>10~ F2 <CSI>1~ <CSI>11~
F3 <CSI>2~ <CSI>12~ F4 <CSI>3~ <CSI>13~
F5 <CSI>4~ <CSI>14~ F6 <CSI>5~ <CSI>15~
F7 <CSI>6~ <CSI>16~ F8 <CSI>7~ <CSI>17~
F9 <CSI>8~ <CSI>18~ F10 <CSI>9~ <CSI>19~
HELP <CSI>?~ <CSI>?~ (same)
Arrow keys:
Up <CSI>A <CSI>T~ Down <CSI>B <CSI>S~
Left <CSI>C <CSI> A~ (notice the space)
Right <CSI>D <CSI> @~ (notice the space)
If you have sent the DEVICE STATUS REPORT command sequence, the
console device returns a cursor position report into your input
stream. It takes the form:
<CSI><row>;<column>R
For example, if the cursor is at column 40, and row 12, here are
the ASCII values you receive in a stream:
9B 34 30 3B 31 32 52
A user may have either moved or resized the window to which your
console is bound. By issuing a WINDOW STATUS REPORT to the con-
sole, you can read the current position and size in the input
stream. This window bounds report takes the following form:
<CSI>1;1;<bottom margin>;<right margin>r
Note that the top and left margins are always 11 for the Amiga.
The bottom and right margins give you the window row and column
dimensions as well. For a window that holds 20 lines with 60
characters per line, you will receive the following in the input
stream:
9B 31 3B 31 3B 32 30 3B 36 30 73
November 17, 1985
- 13 -
If the keyboard information, including "cooked" keystrokes does
not give you enough information about input events you can
request additional information from the console driver.
The command to SET RAW EVENTS is formatted as:
"<CSI>[event-types-separated-by-semicolons]{"
If, for example, you need to know when each key is pressed and
released you would request "RAW keyboard input". This is done by
writing "<CSI>1{" to the console. In a single SET RAW EVENTS
request, you can ask the console to setup for multiple event
types at one time. You must send multiple numeric parameters,
separating them by semicolons (;). Example: ask for gadget
pressed, gadget released and close gadget events - write:
"<CSI>7;8;11{" (all as ASCII characters, without the quotes).
You can reset, that is, delete from reporting, one or more of the
raw input event types by using the RESET RAW EVENTS command, in
the same manner as the SET RAW EVENTS was used to establish them
in the first place. This command stream is formatted as:
<CSI>[event-types-separated-by-semicolons]}
So, for example, you could reset all of the events set in the
above example by transmitting the command sequence:
"<CSI>7;8;11}" Here is a list of the valid raw input event types:
Table 1-3: Raw Input Event Types
REQUEST NUMBER DESCRIPTION
0 nop Used internally.
1 RAW keyboard input. Intuition swallows all by the select
button.
2 RAW mouse input
3 Event Sent whenever your window is made active.
4 Pointer position
5 (unused)
6 Timer
7 Gadget pressed
8 Gadget released
9 Requester activity
10 Menu numbers
11 Close Gadget
12 Window resized
13 Window refreshed
14 Preferences changed (not yet implemented)
15 Disk removed
16 Disk inserted
November 17, 1985
- 14 -
1.7. COMPLEX INPUT EVENT REPORTS
If you select any of these events you will start to get informa-
tion about the events in the following form:
<CSI><class>;<subclass>;<keycode>;<qualifiers>;<x>;<y>;
<seconds>;<microseconds>|
where:
<CSI>
is a one-byte field. It is the "control sequence intro-
ducer", 9B in hex.
<class>
is the RAW input event type, from the above table.
<subclass>
is usually 0. If the mouse is moved to the right controller,
this would be 1.
<keycode>
indicates which key number was pressed (see figure 4-1 and
table 4-5). This field can also be used for mouse informa-
tion.
<qualifiers>
indicates the state of the keyboard and system. The qualif-
iers are defined as follows:
November 17, 1985
- 15 -
Table 1-4: Input Event Qualifiers
BIT MASK KEY
0 0001 left shift
1 0002 right shift
2 0004 capslock *Associated keycode is
special; see below.
3 0008 control
4 0010 left ALT
5 0020 right ALT
6 0040 left Amiga key pressed
7 0080 right Amiga key pressed
8 0100 numeric pad
9 0200 repeat
10 0400 interrupt Not currently used.
11 0800 multi broadcast This window (active one)
or all windows.
12 1000 left mouse button
13 2000 right mouse button
14 4000 middle mouse button (Not available on
standard mouse.)
15 8000 relative mouse Indicates mouse coordinates
are relative, not absolute.
The CAPS LOCK key is handled in a special manner. It only gen-
erates a keycode when it is pressed, not when it is released.
However the up/down bit (80 hex) is still used and reported. If
pressing the caps lock key causes the LED to light then key code
62 (caps lock pressed) is sent. If pressing the caps lock key
extinguishes the LED then key code 190 (caps lock released) is
sent. In effect, the keyboard reports this key as held down
until it is struck again.
The <x> and <y> fields are filled by some classes with an Intui-
tion address: x<<16+y.
The <seconds> and <microseconds> fields contain the system time
stamp taken at the time the event occurred. These values are
stored as long-words by the system.
With RAW keyboard input selected, keys will no longer return a
simple one-character "A" to "Z" but will rather return raw key-
code reports of the form:
<CSI>1;0;<keycode>;<qualifiers>;0;0;<seconds>;<microseconds>|
For example, if the user pressed and released the "B" key with
the left shift and right Amiga keys also pressed you might
receive the following data:
November 17, 1985
- 16 -
<CSI>1;0;35;129;0;0;23987;99|
<CSI>1;0;163;129;0;0;24003;18|
The <keycode> field is an ASCII decimal value representing the
key pressed or released. Adding 128 to the pressed key code will
result in the released keycode. Figure 4-1 lets you convert
quickly from a key to its keycode. The tables let you convert
quickly from a keycode to a key.
Figure 1-1: The Amiga Keyboard, Showing Keycodes in Hex
The default values given correspond to:
1) The values the console device will return when these keys
are pressed, and
2) The Keycaps as shipped with the standard American key-
board.
November 17, 1985
- 17 -
Table 1-5: System Default Console Key Mapping
RAW UNSHIFTED SHIFTED
KEY KEYCAP DEFAULT DEFAULT NUMBER LEGEND VALUE VALUE
00 ` ~ ` (Accent grave) ~ (tilde)
01 1 ! 1 !
02 2 @ 2 @
03 3 # 3 #
04 4 $ 4 $
05 5 % 5 %
06 6 ^ 6 ^
07 7 & 7 &
08 8 * 8 *
09 9 ( 9 (
0A 0 ) 0 )
0B - _ - (Hyphen) _ (Underscore)
0C = + = +
0D \\ | \\ |
0E (undefined)
0F 0 0 0 (Numeric pad)
10 Q q Q
11 W w W
12 E e E
13 R r R
14 T t T
15 Y y Y
16 U u U
17 I i I
18 O o O
19 P p P
1A [{ [ {
1B ] } ] }
1C (undefined)
1D 1 1 1 (Numeric pad)
1E 2 2 2 (Numeric pad)
1F 3 3 3 (Numeric pad)
20 A a A 21 S s S
22 D d D 23 F f F
24 G g G 25 H h H
26 J j J 27 K k K
28 L l L
29 ; : ; :
2A ' " ' (single quote) "
2B (RESERVED) (RESERVED)
2C (undefined)
2D 4 4 4 (Numeric pad)
2E 5 5 5 (Numeric pad)
2F 6 6 6 (Numeric pad)
30 (RESERVED) (RESERVED)
31 Z z Z
32 X x X
33 C c C
34 V v V
35 B b B
36 N n N
37 M m M
38 , < , (comma) <
39 . > . (period) >
3A / ? / ?
3B (undefined)
3C . . . (Numeric pad)
3D 7 7 7 (Numeric pad)
3E 8 8 8 (Numeric pad)
3F 9 9 9 (Numeric pad)
40 (Space bar) 20 20
41 BACKSPACE 08 08
42 TAB 09 09
43 ENTER 0D 0D (Numeric pad)
44 RETURN 0D 0D
45 ESC 1B 1B
46 DEL 7F 7F
47 (undefined)
November 17, 1985
- 18 -
48 (undefined)
49 (undefined)
4A - - - (Numeric Pad)
4B (undefined)
4C Up Arrow <CSI>A~ <CSI>T~
4D Down Arrow <CSI>B~ <CSI>S~
4E Forward Arrow <CSI>C~ <CSI> A~ [1]
4F Backward Arrow <CSI>D~ <CSI> @~
_________________________
[1] In shifted Forward Arrow and Backward arrow, note
blank space after <CSI>.
November 17, 1985
- 19 -
RAW UNSHIFTED SHIFTED
KEY KEYCAP DEFAULT DEFAULT NUMBER LEGEND VALUE VALUE
50 F1 <CSI>0~ <CSI>10~
51 F2 <CSI>1~ <CSI>11~
52 F3 <CSI>2~ <CSI>12~
53 F4 <CSI>3~ <CSI>13~
54 F5 <CSI>4~ <CSI>14~
55 F6 <CSI>5~ <CSI>15~
56 F7 <CSI>6~ <CSI>16~
57 F8 <CSI>7~ <CSI>17~
58 F9 <CSI>8~ <CSI>18~
59 F10 <CSI>9~ <CSI>19~
5A (undefined)
5B (undefined)
5C (undefined)
5D (undefined)
5E (undefined)
5F HELP <CSI>?~ <CSI>?~
November 17, 1985
- 20 -
KEY KEYCAP NUMBER LEGEND
60 SHIFT (left of space bar)
61 SHIFT (right of space bar)
62 CAPS LOCK
63 CTRL
64 (Left) ALT
65 (Right) ALT
66 Amiga (left of space bar) Close Amiga
67 Amiga (right of space bar) Open Amiga
68 Left mouse button Inputs are only for the
one (not converted) mouse connected to Intuition
69 Right mouse button currently "gameport"
one. (not converted)
6A Middle mouse button (not converted)
6B (undefined)
6C (undefined)
6D (undefined)
6E (undefined)
6F (undefined)
November 17, 1985
- 21 -
center; l10 l. RAW KEY NUMBER FUNCTION
70-7F (undefined)
80-F8 Up transition (release or unpress key of one
of the above keys). 80 for 00, F8 for 7F.
F9 Last keycode was bad (was sent in order to
resynchronize).
FA Keyboard buffer overflow.
FB (undefined, reserved for keyboard processor
catastrophe)
FC Keyboard selftest failed.
FD Power-up key stream start. Keys pressed or
stuck at power-up will be sent between FD and FE.
FE Power-up key stream end.
FF (undefined, reserved)
FF Mouse event, movement only, no button change.
(not converted)
Notes about the preceding table:
1) "(undefined)" indicates that the current keyboard design
should not generate this number. If you are using Set-
KeyMap() to change the key map the entries for these
numbers must still be included.
2) "(not converted)" refers to mouse button events. You
must use the sequence "<CSI>2{" to inform the console
driver that you wish to receive mouse events; otherwise
these will not be transmitted.
3) "(RESERVED)" Indicates that these keycodes have been
reserved for non-US keyboards. The "2B" code key will be
between the double-quote(") and RETURN keys. The "30"
code key will be between the SHIFT and "Z" keys.
1.8. KEYMAPPING
The Amiga has the capability of mapping the keyboard in any
manner that you wish. In other computers, this capability is
normally provided through the use of "keyboard enhancers". In
the Amiga, however, the capability is already present and the
vectors that control the remapping are user accessible.
The functions called GetKeyMap() and SetKeyMap() each deal with a
set of 8 longword pointers, known as the KeyMap data structure.
The KeyMap data structure is shown below.
November 17, 1985
- 22 -
struct KeyMap {
APTR km_LoKeyMapTypes;
APTR km_LoKeyMap;
APTR km_LoCapsable;
APTR km_LoRepeatable;
APTR km_HiKeyMapTypes;
APTR km_HiKeyMap;
APTR km_HiCapsable;
APTR km_HiRepeatable;
};
GetKeyMap() returns a pointer to this table of pointers, showing
where in memory each of the tables representing the keymapping
may be found.
As a prelude to the following material, note that the Amiga key-
board transmits raw key information to the computer in the form
of a key position and a transition. Figure 4-1 shows a physical
layout of the keys and the hexadecimal number that is transmitted
to the system when a key is pressed. When the key is released,
its value, plus hexadecimal 80, is transmitted to the computer.
The key mapping described herein refers to the translation from
this raw key transmission into console device output to the user.
The low key map provides translation of the key values from hex
00-3F; the high key map provides translation of key value from
hex 40-67.
Raw output from the keyboard for the LoKeyMap does not include
the space bar, TAB, ALT, CTRL, arrow keys and several other keys
(shown in HiKeyMap, below).
Figure 1-2: Low Key Map Translation Table
November 17, 1985
- 23 -
Table 1-6: High Key Map Hex Values
40 Space
41 Backspace
42 Tab
43 Enter
44 Return
45 Escape
46 Delete
4A Numeric Pad
4C Cursor Up
4D Cursor Down
4E Cursor Forward
4F Cursor Backward
50-59 Function keys F1-F10
5F Help
60 Left Shift
61 Right Shift
62 Caps Lock
63 Control
64 Left Alt
65 Right Alt
66 Left Amiga
67 Right Amiga
The keymap table for the low and high keymaps consists of 4-byte
entries, one per hex keycode. These entries are interpreted in
one of two possible ways:
a. as 4 separate bytes, specifying how the key is to be
interpreted when pressed:
o alone
o with one qualifier
o with another qualifier
o with both qualifiers
where a qualifier is one of three possible keys:
o CTRL (control)
o ALT
o SHIFT
b. as a longword containing the address of a string descrip-
tor, where a string of hex digits is to be output when
this key is pressed. If a string is to be output, any
combination of qualifiers may affect the string that may
be transmitted.
NOTE: The keymap table must begin aligned on a word boundary.
Each entry is 4-bytes long, thereby maintaining word alignment
throughout the table. This is necessary since some of the
entries may be longword addresses and must be aligned properly
for the 68000.
As you may have noticed, there are three possible qualifiers, but
only a 4-byte space in the table for each key. This does not
allow space to describe what the computer should output for all
possible combinations of qualifiers. This problem is solved by
November 17, 1985
- 24 -
only allowing all three qualifiers to affect the output at the
same time in string mode. Here is how that works.
For "vanilla" keys, such as the alphabetic keys, use the 4 bytes
to represent the data output for the key alone, shifted key,
ALT'ed key, and shifted-and-ALT'ed key. Then for the CTRL-key-
plus-vanilla-key, use the code for the key alone with bits 6 and
5 set to 0.
For other keys, such as the return key or escape key, the qualif-
iers specified in the keytypes table (up to two) are the qualif-
iers used to establish the response to the key. This is done as
follows. In the keytypes table, the values listed for the key
types are those listed for the qualifiers in keymap.h and
keymap.i. Specifically, these qualifier equates are:
KC_NOQUAL 0x00
KCF_SHIFT 0x01
KCF_ALT 0x02
KCF_CONTROL 0x04
KC_VANILLA 0x07
KCF_DOWNUP 0x08
KCF_STRING 0x40
As shown above, the qualifiers for the various types of keys
occupy specific bit positions in the key types control byte.
A keymap table entry looks like this, in assembly code:
SOME_KEY:
DC.B VALUE_1, VALUE_2, VALUE_3, VALUE_4
Here is how you interpret the keymap for various combinations of
the qualifier bits:
November 17, 1985
- 25 -
Table 1-7: Keymap Qualifier Bits
If Keytype is: Then value in this position in the
keytable is out put when the key is
pressed along with:
KC_NOQUAL - - - alone
KCF_SHIFT - - SHIFT alone
KCF_ALT - - ALT alone
KCF_CONTROL - - CTRL alone
KCF_ALT+KCF_SHIFT SHIFT+ALT ALT SHIFT alone
KCF_CONTROL+KCF_ALT CTRL+ALT CTRL ALT alone
KCF_CONTROL+KCF_SHIFT CTRL+SHIFT CTRL SHIFT alone
KC_VANILLA SHIFT+ALT ALT SHIFT alone*
* special case-CTRL key, when pressed with one of the al-
phabet keys and certain others, is to output key-alone
value with the bits 6 and 5 set to zero.
The vectors named km_LoKeyTypes and km_HiKeyTypes contain one
byte per raw key code. This byte defines the entry type that is
made in the key table by a set of bit positions.
Possible key types are:
o any of the qualifier groupings noted above, or
o KCF_STRING + any combination of KCF_SHIFT, KCF_ALT,
KCF_CONTROL (or KC_NOQUAL) if the result of pressing the
key is to be a stream of bytes (and key-with-one-or-
more-qualifiers is to be one or more alternate streams of
bytes).
Any key can be made to output up to 8 unique byte streams
if KCF_STRING is set in its keytype. The only limitation
is that the total length of all of the strings assigned
to a key be within the "jump range" of a single byte
increment. See the "String-Output Keys" section below
for more information.
The low keytype table covers the raw keycodes from hex 00-3F, and
contains one byte per keycode. Therefore this table contains 64
(decimal) bytes. The high keytype table covers the raw keycodes
from hex 40-67, and contains 38 (decimal) bytes.
When a key is to output a string, the keymap table contains the
address of a string descriptor in place of a 4-byte mapping of a
key as shown above. Here is a partial table for a new high key
map table which contains only three entries thus far. The first
November 17, 1985
- 26 -
two are for the space bar and the backspace key; the third is for
the tab key, which is to output a string that says "[TAB]". An
alternate string, "[SHIFTED-TAB]", is also to be output when a
shifted TAB key is pressed.
Table 1-8: Composing an Alternate Key Map
newHiMapTypes:
DC.B KCF_ALT,KC_NOQUAL,
DC.B KCF_STRING+KCF_SHIFT, ... ;(more)
newHiMap:
DC.B 0,0,$A0,$20 ;space bar, and ALT-space bar
DC.B 0,0,0,$08 ;BACKSPACE key only
DC.L newkey42 ;new definition for string to
;output for TAB key ... ;(more)
newkey42:
DC.B new42ue - new42us ;length of the
;unshifted string
DC.B new42us - newkey42
;number of bytes from start of
;string descriptor to start of
;this string
DC.B new42se - new42ss ;length of the shifted string
DC.B new42ss - newkey42
;number of bytes from start of
;string descriptor to start of
;this string
new42us:
DC.B '[TAB]'
new42ue:
new42ss:
DC.B '[SHIFTED-TAB]'
new42se:
The new high map table points to the string descriptor at address
newkey42. The new high map types table says that there is one
qualifier, which means that there are two strings in the key
string descriptor.
Each string in the descriptor takes two bytes in this part of the
table; the first byte is the length of the string, the second
byte is the distance from the start of the descriptor to the
start of the string. Therefore, a single string (KCF_STRING +
KC_NOQUAL) takes 2 bytes of string descriptor. If there is one
qualifier, 4 bytes of descriptor are used. If there are two
qualifiers, 8 bytes of descriptor are used. If there are 3 qual-
ifiers, 16 bytes of descriptor are used. All strings start
immediately following the string descriptor in that they are
November 17, 1985
- 27 -
accessed as single byte offsets from the start of the descriptor
itself. Therefore, the distance from the start of the descriptor
to the last string in the set (the one that uses the entire set
of specified qualifiers) must start within 255 bytes of the
descriptor address.
Since the length of the string is contained in a single byte, the
length of any single string must be 255 bytes or less while also
meeting the "reach" requirement.
The length of a keymap containing string descriptors and strings
is variable and depends on the number and size of the strings
that you provide.
The vectors called km_LoCapsable and km_HiCapsable point to the
first byte in an 8-byte table that contains more information
about the keytable entries.
Specifically, if the CAPS LOCK key has been pressed the CAPS LOCK
LED is on), and if there is a bit on in that position in the
capsable map, then this key will be treated as though the shift-
key is now currently pressed. For example, in the default key
mapping, the alphabetic keys are "capsable" but the punctuation
keys are not. This allows you to set the shift-lock, just as on
a normal typewriter, and get all capital letters. However,
unlike a normal typewriter, you need not go out of shift-lock to
correctly type the punctuation symbols or numeric keys.
In the table, the bits that control this feature are numbered
from the lowest bit in the byte, and from the lowest memory byte
address to the highest. For example, the bit representing caps-
able status for the key that transmits raw code 00 is bit 0 in
byte 0; for the key that transmits raw code 08 it's bit 0 in byte
1, and so on.
There are 64 bits (8-bytes) in each of the two capsable tables.
For both the low and high key maps there is an 8-byte table that
provides one bit per possible raw key code. This bit indicates
whether or not the specified key should repeat at the rate set by
the Preferences program. The bit positions correspond to those
specified in the capsable bit table.
If there is a 1 in a specific position, the key can repeat. The
vectors that point to these tables are called km_LoRepeatable and
km_HiRepeatable.
In the default low key map, all of the keys are treated in the
same manner. That is:
o When pressed alone, they transmit the ASCII equivalent of
November 17, 1985
- 28 -
the unshifted key.
o When shifted, they translate the ASCII equivalent of the
shifted value when printed on the keycap.
o When "ALT'ed" (pressed along with an ALT key), they
transmit the alone-value with the high bit of a byte set
(value plus hex 80).
When shifted and ALT'ed, they transmit the shifted-value
plus hex 80.
In this table, the bytes that describe the data to be transmitted
are positioned as the example for the "A" key shown here:
center; l l l l.
key_A DC.B ('A')+$80 ;shifted and ALT'ed
DC.B ('a')+$80 ;ALT'ed only
DC.B ('A') ;shifted only
DC.B ('a') ;not shifted or ALT'ed.
In addition to the response to the key alone, shifted, ALT'ed and
shifted-and-ALT'ed, the default low keymap also responds to the
key combination of "CTRL + key" by stripping off bits 6 and 5 of
the generated data byte. For example, CTRL + A generates the
translated keycode 01 (61 with bits 6 and 5 set to 0).
All keys in the low key map are mapped to their ASCII equivalents
as noted in the low key map key table shown above.
Since the low key table contains 4 bytes per key, and describes
the keys (raw codes) from hex 00-3F, there are 64 times 4 or 256
bytes in this table.
Most of the keys in the high key map generate strings rather than
single character mapping. The following keys map characters with
no qualifier, along with their byte mapping:
KEY GENERATES VALUE:
BACKSP $08 ENTER $0D DEL $7F
November 17, 1985
- 29 -
The following keys map characters and use a single qualifier:
KEY GENERATES VALUE: IF USED WITH QUALIFIER,
GENERATES VALUE:
SPACE $20 $A0 (qualifier = ALT)
RETURN $0D $0A (qualifier = CONTROL)
ESC $1B $9B (qualifier = ALT)
numeric pad '-' $2D $FF (qualifier = ALT)
The following keys generate strings:
KEY GENERATES VALUE: IF USED WITH <SHIFT>,
GENERATES VALUE:
TAB $09 $9B, followed by 'Z'
cursor:
UP $9B, followed by 'A' $9B, followed by 'T'
DOWN $9B, followed by 'B' $9B, followed by 'S'
FWD $9B, followed by 'C' $9B, followed by ' ',
followed by '@'
BACKWD $9B, followed by 'D' $9B, followed by ' ',
followed by 'A'
function keys:
F1 $9B, followed by '0~' $9B, followed by '10~'
F2 $9B, followed by '1~' $9B, followed by '11~'
F3 $9B, followed by '2~' $9B, followed by '12~'
F4 $9B, followed by '3~' $9B, followed by '13~'
F5 $9B, followed by '4~' $9B, followed by '14~'
F6 $9B, followed by '5~' $9B, followed by '15~'
F7 $9B, followed by '6~' $9B, followed by '16~'
F8 $9B, followed by '7~' $9B, followed by '17~'
F9 $9B, followed by '8~' $9B, followed by '18~'
F10 $9B, followed by '9~' $9B, followed by '19~'
HELP $9B, followed by '?~' (no qualifier used)
November 17, 1985
- 30 -
1.9. CLOSING A CONSOLE DEVICE
When you have finished using a console, it must be closed so that
the memory areas it utilized may be returned to the system memory
manager. Here is a sequence that you can use to close a console
device:
CloseDevice(requestBlock);
Note that you should also delete the messages and ports associ-
ated with this console after the console has been closed:
DeleteStdIO(consoleWriteMsg);
DeleteStdIO(consoleReadMsg);
DeletePort(consoleWritePort);
DeletePort(consoleReadPort);
If you have finished with the window used for the console device,
you can now close it.
November 17, 1985